// Connection class definition
//
// Created: Daly 2012-04-01

#include <xnt_event.h>
#include "ax_common.h"

AxConnection::AxConnection() : rbuf(NULL), wbuf(NULL)
{
	reset(1000, 100);	
}

AxConnection::AxConnection(unsigned int rsize, unsigned int wsize) : rbuf(NULL), wbuf(NULL)
{
	reset(rsize, wsize);	
}

void AxConnection::reset(unsigned int rsize, unsigned int wsize)
{
	handle = fd = 0;
	type = CONN_INVALID;	
	rev.mask = wev.mask = 0;
	if (rbuf) delete rbuf;
	rbuf = new AxNetBuffer(rsize);
	if (wbuf) delete wbuf;
	wbuf = new AxNetBuffer(wsize);	
	strcpy(remote_ip, "0.0.0.0");
	remote_port = 0;
	next = NULL;
	cmd_recv = 0;

}

AxConnection::~AxConnection()
{
	delete rbuf;
	delete wbuf;	
}

void AxConnection::set_addr(struct sockaddr_in* addr)
{
	strcpy(remote_ip, inet_ntoa(addr->sin_addr));
	remote_port = ntohs(addr->sin_port);
}

//call os read, don't do more process
int AxConnection::read()
{
	int nbytes;
	static char tmpbuf[2048];
	nbytes = ::read(fd, tmpbuf, 2048); 
	if (nbytes <= 0) return nbytes;
	//push to buffer 	
	rbuf->push(tmpbuf, nbytes);
	return nbytes;
}

void AxConnection::close()
{
	xnt_del_event(&rev, fd, XNT_EV_READ);
	if (wev.mask == XNT_EV_WRITE) xnt_del_event(&wev, fd, XNT_EV_WRITE);
	type = CONN_INVALID;
	handle = cmd_recv = 0;
	::close(fd);
	strcpy(remote_ip, "0.0.0.0");
    remote_port = 0;
	fd = 0;
}

//send data in wbuf
int AxConnection::send_remain()
{
	char* p;
	int len = wbuf->size();
	int ret;
	if (len < 1) return 0;
	p = wbuf->datap();
	ret = ::send(fd, p, len, 0);
	if (ret > 0) wbuf->pop(ret);
	return ret;	 	
}

void AxConnection::set_handler(int which, xnt_event_proc func)
{
	if (type == CONN_INVALID) return;
	if (which == XNT_EV_READ) {
		rev.handler = func;
		xnt_add_event(&rev, fd, XNT_EV_READ);
	} else if (which == XNT_EV_WRITE) {
		wev.handler = func;
		xnt_add_event(&wev, fd, XNT_EV_WRITE);
	}
}

//Listener======================================

AxListen::AxListen()
{
	_backend = 0;
	_listening = 0;
	_fd = 0;
}

AxListen::~AxListen()
{
	//if (_fd > 0) close(_fd);
}

int AxListen::listen(unsigned short port, int backend)
{
	struct sockaddr_in sin;
	int optval = 1;

	bzero(&sin, sizeof(sin));
	_fd = socket(AF_INET, SOCK_STREAM, 0);	
	if (_fd == -1) {
		ax_debug("cannot bind listener");
		return -1;
	}
	if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, 
				(char *) &optval, sizeof(optval)) == -1)
	{
		ax_debug("cannot set REUSEADDR for listener");
		return -1;
	}

	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = INADDR_ANY;
	sin.sin_port = htons((unsigned short)port);
	if (::bind(_fd, (struct sockaddr *)&sin, sizeof(sin)) == -1)
	{
		ax_debug("cannot bind listener port=");
		return -2;
	}
	ax_set_nonblock(_fd);
	_port = port;
	_listening = 1;
	::listen(_fd, backend);
	ax_debug("start listening port= %d", port);
	return 0;
}




